#include <glib.h>
#include <gtk/gtk.h>
#include <SDL.h>
#include "racanhack.h"
#include "task.h"
#include "video.h"
#include "cave.h"
#include "player.h"
#include "monster.h"
#include "monster2.h"
#include "object.h"
#include "stair.h"
#include "floor.h"
#include "turn.h"
#include "los.h"
#include "mapchips.h"
#include "lookdown.h"
#include "main.h"

void turn_trans_state(state (*fp)(struct _task *task), struct _turn *turn)
{
  if (turn->task != NULL) turn->task->alive = FALSE;
  turn->task = task_add(fp, turn);
}

void turn_init()
{
}

void turn_free()
{
}

struct _turn *turn_add()
{
  struct _turn *turn;
  turn = &Turn;
  turn->task = NULL;
  return turn;
}

state turn_player_turn_start(struct _task *task)
{
  struct _turn *turn;
  turn = (struct _turn *)task->pointer[0];
  g_assert(Player.task->fp == player_turn_end);
  lookdown_update();
  player_trans_state(player_turn_start, &Player);
  turn_trans_state(turn_wait_player_turn_end, turn);
  return;
}

state turn_wait_player_turn_end(struct _task *task)
{
  struct _turn *turn;
  GList *li;
  struct _monster *monster;
  turn = (struct _turn *)task->pointer[0];
  if (Player.task->fp == player_turn_end) {
    for (li = g_list_first(curf->monster_list); li != NULL; li = g_list_next(li)) {
      monster = (struct _monster *)li->data;
      if (monster->damage == DODGED_DAMAGE) {
	monster_player_trans_state(monster_dodge_player, monster, &Player);
	return;
      };
      if (monster->damage > 0) {
	monster_player_trans_state(monster_damage_by_player, monster, &Player);
	return;
      };
    };
    lookdown_update();
    turn_trans_state(turn_monster_turn_start, turn);
    return;
  };
}

state turn_monster_turn_start(struct _task *task)
{
  struct _turn *turn;
  GList *li;
  struct _monster *monster;
  turn = (struct _turn *)task->pointer[0];
  for (li = g_list_first(curf->monster_list); li != NULL; li = g_list_next(li)) {
    monster = (struct _monster *)li->data;
    g_assert(monster->task->fp == monster_turn_end);
    monster_trans_state(monster_turn_start, monster);
  };
  turn_trans_state(turn_wait_monster_turn_end, turn);
  return;
}

state turn_wait_monster_turn_end(struct _task *task)
{
  struct _turn *turn;
  GList *li;
  struct _monster *monster;
  turn = (struct _turn *)task->pointer[0];
  for (li = g_list_first(curf->monster_list); li != NULL; li = g_list_next(li)) {
    monster = (struct _monster *)li->data;
    if (!((monster->task->fp == monster_turn_wait_attack) || 
        (monster->task->fp == monster_turn_end))) {
      return;
    };
  };
  turn_trans_state(turn_monster_turn_attack_start, turn);
  return;
}

state turn_monster_turn_attack_start(struct _task *task)
{
  struct _turn *turn;
  GList *li;
  struct _monster *monster;
  turn = (struct _turn *)task->pointer[0];
  if (Player.task->fp != player_turn_end) return;
  for (li = g_list_first(curf->monster_list); li != NULL; li = g_list_next(li)) {
    monster = (struct _monster *)li->data;
    if (monster->task->fp == monster_turn_wait_attack) {
      monster_trans_state(monster_turn_attack, monster);
      turn->attacking_monster = monster;
      turn_trans_state(turn_wait_monster_turn_attack_end, turn);
      return;
    };
  };
  if (g_random_int_range(0, 150) == 0) {
    struct _coord c;
    c = rand_coord();
    if (!is_los_onsight(c)) {  
      monster = monster_add();
      monster->coord = c;
      monster->sprite = video_sprite_add(Z_ORDER_MONSTER);
      monster_trans_state(monster_turn_end, monster);
    };
  };
  turn_trans_state(turn_player_turn_start, turn);
  return;
}

state turn_wait_monster_turn_attack_end(struct _task *task)
{
  struct _turn *turn;
  turn = (struct _turn *)task->pointer[0];
  if (turn->attacking_monster->task->fp == monster_turn_end) {
    turn_trans_state(turn_monster_turn_attack_start, turn);
    return;
  };
}
